package com.cabal.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cabal.aliyun.AliyunSmsUtil;
import com.cabal.auth.dao.CabalAuthMapper;
import com.cabal.auth.dao.CabalBlackListMapper;
import com.cabal.auth.dao.CabalDungeonRecordMapper;
import com.cabal.auth.dao.CabalGatewayGameConfigMapper;
import com.cabal.auth.dto.*;
import com.cabal.auth.entity.CabalBlackList;
import com.cabal.auth.entity.CabalDungeonRecord;
import com.cabal.auth.entity.CabalGatewayGameConfig;
import com.cabal.auth.service.ICabalCommonService;
import com.cabal.auth.vo.CabalAuthVo;
import com.cabal.common.constants.SystemConstants;
import com.cabal.common.encrypt.AESUtils;
import com.cabal.common.util.CabalJsonUtil;
import com.cabal.common.util.DateApiUtil;
import com.cabal.common.util.HttpClientUtil;
import com.cabal.common.util.SnowflakeIdUtil;
import com.cabal.config.DynamicDataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.Charset;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class CabalCommonServiceImpl implements ICabalCommonService {

    private static String ALIYUN_CHECK_PHONE_URL = "https://jisusjhmcx.market.alicloudapi.com/shouji/query?shouji=";

    private static String CHECKPHONE_APPCODE = "APPCODE 02e117cf2c8f4c87878f7865192c9271";

    private static final String CABAL_CODE = "CABAL_CODE";

    private static final String IP_ADDRESS_CHECK = "https://qryip.market.alicloudapi.com/lundear/qryip?";

    private static final String IP_ADDRESS_APP_CODE = "02e117cf2c8f4c87878f7865192c9271";

    @Value("${loginNum}")
    private Integer loginNum;

    @Autowired
    private HttpServletRequest request;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private CabalAuthMapper cabalAuthMapper;

    @Value("${checkPhone:false}")
    private Boolean checkPhone;

    @Value("${register.on-off:true}")
    private Boolean registerOn;

    @Resource
    private CabalDungeonRecordMapper cabalDungeonRecordMapper;

    @Resource
    private CabalGatewayGameConfigMapper cabalGatewayGameConfigMapper;

    public static Map<Integer, String> DUNGEON_MAP = new HashMap<>();

    @Resource
    private CabalBlackListMapper cabalBlackListMapper;

    static {
        DUNGEON_MAP.put(50, "4111-[QL]火山心脏的邀请函(团队副本)");
        DUNGEON_MAP.put(126, "4341-损坏的亡者护符");
        DUNGEON_MAP.put(115, "4301-[QL]帕莱斯特拉炼狱");
        DUNGEON_MAP.put(24, "293-黑暗印章");
        DUNGEON_MAP.put(57, "4118-疾驰列车");
        DUNGEON_MAP.put(88, "4263-亡者的护身符 (B3F)");
        DUNGEON_MAP.put(121, "4336-亡者的护身符B3F（Part2）");
        DUNGEON_MAP.put(127, "4342-天灾遗迹B3F");
        DUNGEON_MAP.put(58, "4119-新的冰冻线索");
        DUNGEON_MAP.put(90, "4265-遗忘之岛（觉醒模式）");
        DUNGEON_MAP.put(107, "4283-奇妙的试剂");
        DUNGEON_MAP.put(111, "4339-幻影的启示录外传");
        DUNGEON_MAP.put(122, "4347-玻璃瓶");
        DUNGEON_MAP.put(124, "4344-恶魔的钥匙");
        DUNGEON_MAP.put(125, "4346-恶魔的邀请函");
        DUNGEON_MAP.put(120, "4351-神秘的石雕");
        DUNGEON_MAP.put(117, "4352-古老的龙石板");
        DUNGEON_MAP.put(116, "4362-照亮灵魂的灯火");
        DUNGEON_MAP.put(51, "4112-古代先锋的邀请函(团队副本)");
        DUNGEON_MAP.put(85, "4259-被污染的仙人掌");
        DUNGEON_MAP.put(87, "4262-全息地图");
        DUNGEON_MAP.put(23, "294-天灾遗迹 B1");
        DUNGEON_MAP.put(86, "4260-损坏的电路芯片");
        DUNGEON_MAP.put(96, "4270-山地雷达");
        DUNGEON_MAP.put(81, "4255-神秘的树枝");
    }

    public String checkBlackPhone(String phone) {
        Map<String, String> param = new HashMap<>();
        param.put("Authorization", CHECKPHONE_APPCODE);
        String resultJson = HttpClientUtil.doGetJson(ALIYUN_CHECK_PHONE_URL.concat(phone), param);
        log.info("调用手机核验接口响应参数:" + resultJson);
        AliyunCheckPhoneResponse aliyunCheckPhoneResponse = CabalJsonUtil.json2pojo(resultJson, AliyunCheckPhoneResponse.class);

        if(aliyunCheckPhoneResponse != null
                && aliyunCheckPhoneResponse.getResult() != null) {
            return aliyunCheckPhoneResponse.getResult().getCompany();
        }
        return "";
    }

    public boolean checkIpAddress(String ipAddress) {
        boolean checkResult = true;
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Authorization", "APPCODE " + IP_ADDRESS_APP_CODE);

        String requestUrl = "https://qryip.market.alicloudapi.com/lundear/qryip?ip=" + ipAddress;
        try {
            String response = HttpClientUtil.doGetJson(requestUrl, headers);
            log.info("IP地址归属地查询返回结果>>>>" + response);
            AliyunCheckIpAddressResponse aliyunCheckIpAddressResponse = CabalJsonUtil.json2pojo(response, AliyunCheckIpAddressResponse.class);
            if(aliyunCheckIpAddressResponse != null &&
                    aliyunCheckIpAddressResponse.getResult() != null &&
                    aliyunCheckIpAddressResponse.getResult().getCheckIpAddressInfo() != null) {
                CheckIpAddressInfo checkIpAddressInfo = aliyunCheckIpAddressResponse.getResult().getCheckIpAddressInfo();
                String province = checkIpAddressInfo.getProvince();
                String city = checkIpAddressInfo.getCity();
                String district = checkIpAddressInfo.getDistrict();
                if("四川省".equals(province) && "成都市".equals(city) && "锦江区".equals(district)) {
                    checkResult =  false;
                }
            }
        } catch (Exception e) {
            log.error("调用IP地址查询接口出错", e);
        }

        return checkResult;
    }

    @Override
    public String register(CabalUserInfoDTO cabalUserInfoDTO) {
        DynamicDataSourceContextHolder.removeContextKey();

        // 验证码校验
        if(!checkVerifyCode(cabalUserInfoDTO)) {
            return "短信验证码无效！";
        }

        // 判断帐号是否已被注册
        int accountCount = cabalAuthMapper.countAccount(cabalUserInfoDTO.getLoginAccount());
        if(accountCount > 0) {
            return "该账号已被注册，请重新填写账号注册！";
        }

        try {
            String loginAccount = cabalUserInfoDTO.getLoginAccount();
            // 判断账号是否包含手机验证码，如果包含则自动去掉进行注册
            if(loginAccount.length() > 6) {
                if(loginAccount.substring(loginAccount.length() -6).equals(cabalUserInfoDTO.getSmsVerifyCode())) {
                    loginAccount = loginAccount.substring(0, loginAccount.length() -6);
                }
            }

            // 注册信息插入数据库
            log.info("{}帐号注册信息>>>>{}", cabalUserInfoDTO.getLoginAccount(), CabalJsonUtil.obj2json(cabalUserInfoDTO));
            Map<String, Object> params = new HashMap<>();
            params.put("loginAccount", loginAccount);
            params.put("password", cabalUserInfoDTO.getPassword());
            params.put("email", "sk.com");
            params.put("question", "我的宠物名字是？");
            params.put("answer", "123");
            String ip = HttpClientUtil.getClientIp(request);
            params.put("lastIp", ip);
            int insertResult = cabalAuthMapper.insertAccount(params);
            // 根据新增ID，更新其他字段信息
            cabalAuthMapper.updateCabalUserInfoById(cabalUserInfoDTO, insertResult);

            if(stringRedisTemplate.hasKey(SystemConstants.CABAL_BLACK_PHONE_KEY.concat(cabalUserInfoDTO.getPhoneNum()))) {
                // 存在黑户手机号，封禁账号直接return
                log.info("根据手机号黑户封禁>>>>" + cabalUserInfoDTO.getPhoneNum());
                cabalAuthMapper.updateAuthTypeByPhone(cabalUserInfoDTO.getPhoneNum());
            }

        } catch (Exception e) {
            log.error("{}账号注册出错", cabalUserInfoDTO.getLoginAccount(), e);
            return "FAIL";
        }
        return "SUCCESS";
    }

    public boolean checkVerifyCode(CabalUserInfoDTO cabalUserInfoDTO) {
        String key = CABAL_CODE.concat(cabalUserInfoDTO.getPhoneNum());
        String code = stringRedisTemplate.opsForValue().get(key);
        stringRedisTemplate.delete(key);
        if (StringUtils.isBlank(code)) {
            return false;
        }
        return code.equalsIgnoreCase(cabalUserInfoDTO.getSmsVerifyCode());
    }



    @Override
    public String sendMessage(SendMessageDTO dto, String ip) {
        DynamicDataSourceContextHolder.removeContextKey();

        // IP地址查询
        if(!checkIpAddress(ip)) {
            log.info("非法IP[{}]在发送短信, 手机号>>>>{}", ip, dto.getPhone());
            stringRedisTemplate.opsForValue().set(SystemConstants.CABAL_BLACK_PHONE_KEY.concat(dto.getPhone()), ip);
            return "SUCCESS";
        }

        // 调用平台验证手机真实性
        String company = checkBlackPhone(dto.getPhone());
        String signName = "skcabal";
        if(company.contains("移动")) {
            signName = "贵州河佳运输有限公司";
        }

        // 黑名单校验
        QueryWrapper<CabalBlackList> queryWrapper = new QueryWrapper<CabalBlackList>();
        queryWrapper.lambda().eq(CabalBlackList::getName2, AESUtils.encrypt(dto.getPhone(), AESUtils.ENCRY_KEY));
        int blackListCount =  cabalBlackListMapper.selectCount(queryWrapper);
        if(blackListCount > 0) {
            return "您被光荣列入黑名单，谢谢惠顾！";
        }

        queryWrapper = new QueryWrapper<CabalBlackList>();
        queryWrapper.lambda().eq(CabalBlackList::getLastLoginIp, ip).or()
                .eq(CabalBlackList::getIp, ip);
        blackListCount = cabalBlackListMapper.selectCount(queryWrapper);
        if(blackListCount > 0) {
            return "您被光荣列入黑名单，谢谢惠顾！";
        }

        DynamicDataSourceContextHolder.setContextKey(SystemConstants.DS_KEY_CABALMALL);
        CabalGatewayGameConfig cabalGatewayGameConfig = cabalGatewayGameConfigMapper.selectById(1);
        DynamicDataSourceContextHolder.removeContextKey();
        if(cabalGatewayGameConfig != null) {
            Integer registerAble = cabalGatewayGameConfig.getRegisterAble();
            if(registerAble != null && registerAble == 2) {
                return "暂未开放注册";
            }
        }

        // 校验该手机号是否已经注册过帐号
        if(checkPhone) {
            // 根据IP查询是否存在封禁记录，如果存在则直接返回SUCCESS，并且记录
            int countAuthTypeByIp = cabalAuthMapper.countAuthTypeByIp(ip);
            if(countAuthTypeByIp > 0) {
                log.info("黑IP地址>>>>" + ip + "手机号>>>>" + dto.getPhone());
                //return "劝你做个好人!";
                stringRedisTemplate.opsForValue().set(SystemConstants.CABAL_BLACK_PHONE_KEY.concat(dto.getPhone()), ip);
            }

            int countAuthType = cabalAuthMapper.countAuthTypeByPhone(dto.getPhone());
            if(countAuthType > 0) {
                log.info("黑手机号在请求注册>>>>" + dto.getPhone());
                stringRedisTemplate.opsForValue().set(SystemConstants.CABAL_BLACK_PHONE_KEY.concat(dto.getPhone()), ip);
                //return "劝你做个好人!";
            }

            int count = cabalAuthMapper.countByPhone(dto.getPhone());
            if(count > 1) {
                return "该手机号已注册两个帐号，请使用其他手机号注册!";
            }
        }

        // 验证同一手机号短信发送次数
        String nowDate = DateApiUtil.format(new Date(), DateApiUtil.NORM_DATE_PATTERN);
        String sendCountKey = nowDate + "_" + dto.getPhone();
        String sendCount = stringRedisTemplate.opsForValue().get(sendCountKey);
        if(StringUtils.isNotBlank(sendCount) && Integer.parseInt(sendCount) >= 5) {
            return "该手机号当天短信发送超限，请24小时后再重新注册!";
        }

        String verifyCode = AliyunSmsUtil.sendSmsVerifyCode(dto.getPhone());
        if(StringUtils.isBlank(verifyCode)) {
            return "短信发送失败!";
        }

        log.info("{}短信发送成功，短信验证码为---->{}", dto.getPhone(), verifyCode);

        // 存入redis并设置过期时间checkAccount
        String key = CABAL_CODE.concat(dto.getPhone());
        stringRedisTemplate.opsForValue().set(key, verifyCode, Integer.valueOf(300), TimeUnit.SECONDS);

        // 一天内同一手机号只能发送N条信息，将日期+手机号存入redis
        Integer saveSendCount;
        if(!StringUtils.isBlank(sendCount)) {
            saveSendCount = Integer.parseInt(sendCount) + 1;
        } else {
            saveSendCount = 1;
        }
        stringRedisTemplate.opsForValue().set(sendCountKey, String.valueOf(saveSendCount), Integer.valueOf(1), TimeUnit.DAYS);
        return "SUCCESS";
    }

    @Override
    public String checkAccount(CabalUserInfoDTO cabalUserInfoDTO) {
        DynamicDataSourceContextHolder.removeContextKey();
        int accountCount = cabalAuthMapper.countAccount(cabalUserInfoDTO.getLoginAccount());
        if(accountCount > 0) {
            return "FAIL";
        }
        return "SUCCESS";
    }

    @Override
    public List<String> getAccountByUserName(String userName) {
        Charset latin1Charset = Charset.forName("ISO-8859-1");
        Charset gbkCharset = Charset.forName("GBK");

        byte[] latin1Bytes = userName.getBytes(gbkCharset);
        String decodedText = new String(latin1Bytes, latin1Charset);
        List<String> roleIds = cabalAuthMapper.selectAccountByName(decodedText);
        DynamicDataSourceContextHolder.setContextKey(SystemConstants.DS_KEY_ACCOUNT);
        if(CollectionUtils.isEmpty(roleIds)) {
            return new ArrayList<>();
        }

        List<String> resultList = new ArrayList<>();
        for(String roleId : roleIds) {
            Integer userNum = Integer.parseInt(roleId) / 8;
            // 查询账号
            CabalAuthVo cabalAuthVo = cabalAuthMapper.getCabalAuthVoByUserNum(userNum);
            if(cabalAuthVo == null) {
                continue;
            }
            String account = cabalAuthVo.getUserId();
            log.info("角色账号>>>>" + account);
            resultList.add(account);
        }
        return resultList;
    }

    @Override
    public String batchEncryptPhone() {
        // 查询所有账号表数据集合
        List<CabalAuthVo> cabalAuthVoList = cabalAuthMapper.searchAllAccountList();
        if(CollectionUtils.isEmpty(cabalAuthVoList)) {
            return "没有查到数据";
        }

        cabalAuthMapper.batchEncryptPhone(cabalAuthVoList);
        return "SUCCESS";
    }

    @Override
    public String sendDungeonRecord(SendDungeonRecordDTO sendDungeonRecordDTO, String ipAddress) {
        try {
            String taskId = sendDungeonRecordDTO.getTaskId();
            QueryWrapper<CabalDungeonRecord> queryWrapper = new QueryWrapper<CabalDungeonRecord>();
            queryWrapper.lambda().eq(CabalDungeonRecord::getTaskId, Long.valueOf(taskId));
            DynamicDataSourceContextHolder.setContextKey(SystemConstants.DS_KEY_CABALMALL);
            CabalDungeonRecord cabalDungeonRecord =  cabalDungeonRecordMapper.selectOne(queryWrapper);

            Timestamp currentTime = new Timestamp(new Date().getTime());
            if(cabalDungeonRecord == null) {
                cabalDungeonRecord = new CabalDungeonRecord();
                cabalDungeonRecord.setId(SnowflakeIdUtil.getInstance().nextId());
                cabalDungeonRecord.setTaskId(Long.parseLong(taskId));
                cabalDungeonRecord.setStartTime(currentTime);
                cabalDungeonRecord.setMapId(Integer.parseInt(sendDungeonRecordDTO.getMapId()));
                String mapValue = DUNGEON_MAP.get(Integer.parseInt(sendDungeonRecordDTO.getMapId()));
                if(StringUtils.isNotBlank(mapValue)) {
                    String[] mapArrayValue = mapValue.split("-");
                    cabalDungeonRecord.setDungeonId(Integer.parseInt(mapArrayValue[0]));
                    cabalDungeonRecord.setMapName(mapArrayValue[1]);
                }
                cabalDungeonRecord.setCreateTime(currentTime);
                cabalDungeonRecord.setIpAddress(ipAddress);
                cabalDungeonRecord.setAccount(sendDungeonRecordDTO.getAccount());
                DynamicDataSourceContextHolder.setContextKey(SystemConstants.DS_KEY_CABALMALL);
                cabalDungeonRecordMapper.insert(cabalDungeonRecord);
            } else {
                Date startTime = cabalDungeonRecord.getStartTime();
                cabalDungeonRecord.setEndTime(currentTime);
                cabalDungeonRecord.setUpdateTime(currentTime);

                Integer clearTimeSec = (int)((currentTime.getTime() - startTime.getTime()) / 1000);
                cabalDungeonRecord.setClearTimeSec(clearTimeSec);
                DynamicDataSourceContextHolder.setContextKey(SystemConstants.DS_KEY_CABALMALL);
                cabalDungeonRecordMapper.updateById(cabalDungeonRecord);
            }
        } finally {
            DynamicDataSourceContextHolder.removeContextKey();
        }

        return "SUCCESS";
    }

    public static void main(String[] args) {
        CabalCommonServiceImpl cabalCommonService = new CabalCommonServiceImpl();
        /*CabalCommonServiceImpl cabalCommonService = new CabalCommonServiceImpl();
        String checkPhoneStr = "16722368845";
        String[] checkPhoneList = checkPhoneStr.split(",");

        for(String phone : checkPhoneList) {
            String company = cabalCommonService.checkBlackPhone(phone);
            System.out.println(company);
        }*/
        /*String appcode = "02e117cf2c8f4c87878f7865192c9271";
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Authorization", "APPCODE " + appcode);

        String requestUrl = "https://qryip.market.alicloudapi.com/lundear/qryip?ip=" + "110.184.221.188";
        try {
            String response = HttpClientUtil.doGetJson(requestUrl, headers);
            System.out.println("返回结果>>>>" + response);
        } catch (Exception e) {
            e.printStackTrace();
        }*/

        //boolean result = cabalCommonService.checkIpAddress("110.184.221.288");
        cabalCommonService.checkBlackPhone("18307103337");
        //System.out.println(result);

    }

}
